package com.yk.system.listener;

import cn.hutool.core.collection.CollUtil;
import com.yk.common.core.constant.CacheConstants;
import com.yk.common.redis.service.RedissonUtil;
import com.yk.system.service.ConfigurationRoleService;
import com.yk.system.service.DeviceRoleService;
import com.yk.system.service.DeviceService;
import com.yk.system.service.NotificationService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Redis Key失效事件监听。更新失效分享设备信息缓存
 *
 * @author lmx
 * @date 2023/12/22 9:49
 */
@Slf4j
@Component
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    @Resource
    private RedissonUtil redissonUtil;
    @Resource
    private DeviceRoleService deviceRoleService;
    @Resource
    private DeviceService deviceService;
    @Resource
    private ConfigurationRoleService configurationRoleService;
    @Resource
    private NotificationService notificationService;

    private final List<String> cacheKeyList = CollUtil.newArrayList(
            CacheConstants.DEVICE_ROLE_EXPIRED_TIME_KEY,
            CacheConstants.CONFIGURATION_ROLE_EXPIRED_TIME_KEY,
            CacheConstants.NOTIFICATION_EXPIRED_TIME_KEY,
            CacheConstants.EXPIRE_DEVICE_RESET_CONTROL_KEY
    );

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    @Override
    public void onMessage(Message message, byte[] pattern) {
        String expiredKey = message.toString();
        String prefix = expiredKey.substring(0, expiredKey.indexOf(":") + 1);
        if (!cacheKeyList.contains(prefix)) {
            return;
        }
        // 避免多个服务监听情况下重复消费
        String cacheKey = CacheConstants.EXPIRED_TIME_KEY + expiredKey;
        try {
            RLock lock = redissonUtil.lock(cacheKey, TimeUnit.HOURS, 1L);
            if (!lock.isLocked()) {
                log.error("获取分布式锁失败-key：{}", cacheKey);
                return;
            }
            if (expiredKey.contains(CacheConstants.DEVICE_ROLE_EXPIRED_TIME_KEY)) {
                deviceRoleService.update2Status(expiredKey.replace(CacheConstants.DEVICE_ROLE_EXPIRED_TIME_KEY, ""));
            }
            if (expiredKey.contains(CacheConstants.CONFIGURATION_ROLE_EXPIRED_TIME_KEY)) {
                configurationRoleService.update2Status(expiredKey.replace(CacheConstants.CONFIGURATION_ROLE_EXPIRED_TIME_KEY, ""));
            }
            if (expiredKey.contains(CacheConstants.NOTIFICATION_EXPIRED_TIME_KEY)) {
                notificationService.sendMessage(expiredKey.replace(CacheConstants.NOTIFICATION_EXPIRED_TIME_KEY, ""));
            }
            if (expiredKey.contains(CacheConstants.EXPIRE_DEVICE_RESET_CONTROL_KEY)) {
                deviceService.sendResetWriteEmq(expiredKey.replace(CacheConstants.EXPIRE_DEVICE_RESET_CONTROL_KEY, ""));
            }
        } catch (Exception e) {
            log.error("redis过期监听异常：{}", e.getMessage());
        } finally {
            //释放锁
            redissonUtil.unlock(cacheKey);
        }
    }
}
